LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.all;
LIBRARY altera;
use altera.altera_primitives_components.all;

-- 11:00 -> 14:00

ENTITY DE0 IS
	PORT
	(
		-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --
		-- for prac 6 you will only use the following port signals
		-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --
		CLOCK_50 : IN STD_LOGIC; -- 50MHz in-circuit clock
		LEDG : OUT STD_LOGIC_VECTOR(9 DOWNTO 0); -- the 10 green LEDs on the DE0 board
		SW : IN std_LOGIC_VECTOR(9 DOWNTO 0); -- the 10 switches on the DE0 board
		BUTTON : IN STD_LOGIC_VECTOR(0 TO 2);  -- the 3 buttons on the DE0 board
		HEX0_D : INOUT STD_LOGIC_VECTOR(0 TO 6); -- the LEDs of the 7-segment display (right)
		HEX1_D : INOUT STD_LOGIC_VECTOR(0 TO 6); -- the LEDs of the 7-segment display
		HEX2_D : INOUT STD_LOGIC_VECTOR(0 TO 6); -- the LEDs of the 7-segment display
		HEX3_D : INOUT STD_LOGIC_VECTOR(0 TO 6); -- the LEDs of the 7-segment display (left)

		-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --
		-- ignore the rest of the PORT for prac 6  -- 
		-- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --
		FL_BYTE_N : IN STD_LOGIC;
		FL_CE_N : IN STD_LOGIC;
		FL_OE_N : IN STD_LOGIC;
		FL_RST_N : IN STD_LOGIC;
		FL_RY : IN STD_LOGIC;
		FL_WE_N : IN STD_LOGIC;
		FL_WP_N : IN STD_LOGIC;
		FL_DQ15_AM1 : IN STD_LOGIC;
		PS2_KBCLK : IN STD_LOGIC;
		PS2_KBDAT : IN STD_LOGIC;
		PS2_MSCLK : IN STD_LOGIC;
		PS2_MSDAT : IN STD_LOGIC;
		UART_RXD : IN STD_LOGIC;
		UART_TXD : IN STD_LOGIC;
		UART_RTS : IN STD_LOGIC;
		UART_CTS : IN STD_LOGIC;
		SD_CLK : IN STD_LOGIC;
		SD_CMD : IN STD_LOGIC;
		SD_DAT0 : IN STD_LOGIC;
		SD_DAT3 : IN STD_LOGIC;
		SD_WP_N : IN STD_LOGIC;
		LCD_RW : IN STD_LOGIC;
		LCD_RS : IN STD_LOGIC;
		LCD_EN : IN STD_LOGIC;
		LCD_BLON : IN STD_LOGIC;
		VGA_HS : IN STD_LOGIC;
		VGA_VS : IN STD_LOGIC;
		HEX0_DP : IN STD_LOGIC;
		HEX1_DP : IN STD_LOGIC;
		HEX2_DP : INOUT STD_LOGIC;
		HEX3_DP : IN STD_LOGIC;
		DRAM_CAS_N : IN STD_LOGIC;
		DRAM_CS_N : IN STD_LOGIC;
		DRAM_CLK : IN STD_LOGIC;
		DRAM_CKE : IN STD_LOGIC;
		DRAM_BA_0 : IN STD_LOGIC;
		DRAM_BA_1 : IN STD_LOGIC;
		DRAM_LDQM : IN STD_LOGIC;
		DRAM_UDQM : IN STD_LOGIC;
		DRAM_RAS_N : IN STD_LOGIC;
		DRAM_WE_N : IN STD_LOGIC;
		CLOCK_50_2 : IN STD_LOGIC;
		FL_ADDR : IN STD_LOGIC_VECTOR(0 TO 21);
		FL_DQ : IN STD_LOGIC_VECTOR(0 TO 14);
		GPIO0_D : INOUT STD_LOGIC_VECTOR(0 TO 31);
		GPIO0_CLKIN : IN STD_LOGIC_VECTOR(0 TO 1);
		GPIO0_CLKOUT : IN STD_LOGIC_VECTOR(0 TO 1);
		GPIO1_CLKIN : IN STD_LOGIC_VECTOR(0 TO 1);
		GPIO1_CLKOUT : IN STD_LOGIC_VECTOR(0 TO 1);
		GPIO1_D : IN STD_LOGIC_VECTOR(0 TO 31);
		LCD_DATA : IN STD_LOGIC_VECTOR(0 TO 7);
		VGA_G : IN STD_LOGIC_VECTOR(0 TO 3);
		VGA_R : IN STD_LOGIC_VECTOR(0 TO 3);
		VGA_B : IN STD_LOGIC_VECTOR(0 TO 3);
		DRAM_DQ : IN STD_LOGIC_VECTOR(0 TO 15);
		DRAM_ADDR : IN STD_LOGIC_VECTOR(0 TO 12)
		);
END DE0;

ARCHITECTURE structure OF DE0 IS

-- Component definitions
component hex_display 
	port(	number			: in integer range 0 to 9;
			hex				: out std_logic_vector(6 downto 0));
end component;
component clk_divider is 
	port ( 	clk_in			: in std_logic;
				clk_en			: in std_logic := '1';
				clk_out 			: inout std_logic := '0' );
end component;

signal num_in				: signed (7 downto 0);
signal num_out				: signed (9 downto 0);
signal num_count			: integer range 0 to 10 := 0;
signal num_out_sign		: std_logic;
signal num_out_abs		: signed (9 downto 0);
-- signal memory 				: signed (9 downto 0);

type operation				is (plus, minus, times, div);
signal current_op			: operation;

type state 					is (reading, calculate);
signal current_state		: state := reading;
signal next_state 		: state := reading;
signal counting 			: std_logic := '0';

-- buttons
signal math,calc,recall	: std_logic;
signal clr					: std_logic;


signal hex_out_0, hex_out_1, hex_out_2
								: integer range 0 to 9;
								
begin
	
	-- button definitions
	math				<= button(2);
	calc				<= button(1);
	recall			<= button(0);
	
	-- display definitions
	hex_disp_0	: hex_display port map (number => hex_out_0, hex => hex0_D);
	hex_disp_1	: hex_display port map (number => hex_out_1, hex => hex1_D);
	hex_disp_2	: hex_display port map (number => hex_out_2, hex => hex2_D);
	
	-- number in
	num_in <= signed(sw(9 downto 2));
	num_out_sign <= 
		'1' when (current_state = reading and num_in < 0) or (current_state = calculate and num_out < 0) or (recall = '0' and num_out < 0) else '0';
	
	num_out_abs <= 
		abs(num_out) when current_state = calculate or recall = '0' else 
		("00" & abs(num_in)) when current_state = reading else 
		"0000000000";
	
	-- displays
	hex_out_0 <= to_integer(num_out_abs) rem 10;
	hex_out_1 <= to_integer(num_out_abs) / 10 rem 10;
	hex_out_2 <= to_integer(num_out_abs) / 100 rem 10;
	
	hex3_d <= "1111110" when num_out_sign = '1' else "1111111";

	-- num counter led definitions
	with num_count select ledg <=
		"0000000000" when 0,
		"1000000000" when 1,
		"1100000000" when 2,
		"1110000000" when 3,
		"1111000000" when 4,
		"1111100000" when 5,
		"1111110000" when 6,
		"1111111000" when 7,
		"1111111100" when 8,
		"1111111110" when 9,
		"1010101010" when others;
	
	-- hex2_DP <= '1' when memory = 0 else '0';
	
	-- clock definitions
	clk_div_clr	: clk_divider port map (clk_in => CLOCK_50, clk_out => clr, clk_en => not calc);
	
	-- math button stanum_count <= num_count;te machine
	process(math, clr)
		variable tmp : signed (17 downto 0);
	begin
		if clr = '1' then
			num_out <= (others => '0');
			num_count <= 0;
		elsif math'event and math = '0' then
			if current_state = reading then
				num_count <= num_count + 1;
				-- perform operation
				case sw(1 downto 0) is
					when "00" =>
						num_out <= num_out + num_in;
					when "01" =>
						num_out <= num_out - num_in;
					when "10" =>
						tmp := num_out * num_in;
						num_out <= tmp(9 downto 0);
					when "11" =>
						num_out <= num_out / num_in;
					when others =>
				end case;
			end if;
		end if; 
	end process;

	-- calculate button state machine (next state logic)
	process(calc, clr)
	begin
		if clr = '1' then 
			next_state <= reading;
		elsif calc'event and calc = '0' then
			case current_state is
				when reading =>
					next_state <= calculate;
				when others =>
			end case;
		end if; 
	end process;

	-- state progress only
	-- sets current_state
	process(next_state) 
	begin
		current_state <= next_state;
	end process;

END structure;